﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockManagement.ViewModels;
using System.Collections.ObjectModel;
using StockManagement.Helper;
using StockManagement.Model;

namespace StockManagement.ViewModels
{
    public class ProductPageViewModel : BaseViewModel
    {
        ObservableCollection<MaterialViewModel> _allMaterialCollection;
        ObservableCollection<ProductViewModel> _allProductCollection = new ObservableCollection<ProductViewModel>();
        
        NewProductViewModel _newProductVM;
        EditProductViewModel _editProductVM;
        ProductGridViewModel _productGridVM;
        InwardProductINViewModel _inwardProductINVM;
        InwardProductOUTViewModel _inwardProductOUTVM;
        OutwardProductViewModel _outwardProductVM;

        public ProductPageViewModel(ObservableCollection<MaterialViewModel> materialCollection)
        {
            LoadProductStock();
            _allMaterialCollection = new ObservableCollection<MaterialViewModel>(materialCollection.Where(p=>p.MaterialType == EnumMaterialType.Manufacturing));
            materialCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(materialCollection_CollectionChanged);
        }

        private void LoadProductStock()
        {
            foreach (var item in DataHelper.GetProductList())
            {
                _allProductCollection.Add(item);
            }
        }

        public NewProductViewModel NewProduct
        {
            get
            {
                if (_newProductVM == null)
                {
                    _newProductVM = new NewProductViewModel(_allMaterialCollection);
                    _newProductVM.ProductAdded += new ProductAddedDelegate(_newProductVM_ProductAdded);
                }
                return _newProductVM;
            }
            set
            {
                _newProductVM = value;
                OnPropertyChanged("NewProduct");
            }
        }
        
        public EditProductViewModel EditProduct
        {
            get
            {
                if (_editProductVM == null)
                {
                    _editProductVM = new EditProductViewModel(_allMaterialCollection, _allProductCollection);
                    _editProductVM.ProductDeleted += new ProductDeletedDelegate(_editProductVM_ProductDeleted);
                    _editProductVM.ProductUpdated += new ProdUpdatedDelegate(_editProductVM_ProductUpdated);
                }
                return _editProductVM;
            }
            set
            {
                _editProductVM = value;
                OnPropertyChanged("EditProduct");
            }
        }

        public InwardProductINViewModel InwardProductIN
        {
            get
            {
                if (_inwardProductINVM == null)
                {
                    _inwardProductINVM = new InwardProductINViewModel(_allProductCollection);
                    _inwardProductINVM.OnInwardProductINUpdated += new ProductUpdatedDelegate(OnInwardProductINUpdated);                    
                }
                return _inwardProductINVM;
            }
            set
            {
                _inwardProductINVM = value;
                OnPropertyChanged("InwardProductIN");
            }
        }

        public InwardProductOUTViewModel InwardProductOUT
        {
            get
            {
                if (_inwardProductOUTVM == null)
                {
                    _inwardProductOUTVM = new InwardProductOUTViewModel(_allProductCollection);
                    _inwardProductOUTVM.OnInwardProductOUTUpdated += new ProductUpdatedDelegate(OnInwardProductOUTUpdated);
                }
                return _inwardProductOUTVM;
            }
            set
            {
                _inwardProductOUTVM = value;
                OnPropertyChanged("InwardProductOUT");
            }
        }

        public OutwardProductViewModel OutwardProduct
        {
            get
            {
                if (_outwardProductVM == null)
                {
                    _outwardProductVM = new OutwardProductViewModel(_allProductCollection);
                    _outwardProductVM.OnOutwardProductUpdated += new ProductUpdatedDelegate(OnOutwardProductUpdated);
                }
                return _outwardProductVM;
            }
            set
            {
                _outwardProductVM = value;
                OnPropertyChanged("OutwardProduct");
            }
        }

        public ProductGridViewModel ProductGrid
        {
            get
            {
                if (_productGridVM == null)
                    _productGridVM = new ProductGridViewModel(_allProductCollection);
                return _productGridVM;
            }
            set
            {
                _productGridVM = value;
                OnPropertyChanged("ProductGrid");
            }

        }

        void _newProductVM_ProductAdded()
        {
            _allProductCollection.Add((ProductViewModel)_newProductVM);
            NewProduct = null;
        }
        
        void _editProductVM_ProductUpdated()
        {
            var vm = _allProductCollection.FirstOrDefault(p => p.ProductID == _editProductVM.SelectedProduct.ProductID);
            if (vm == null)
                return;

            vm.ProductName = _editProductVM.ProductName;
            vm.ProductType = _editProductVM.ProductType;
            vm.ProductStatus = _editProductVM.ProductStatus;
            vm.MaterialsQuantity.Clear();

            foreach (var item in _editProductVM.AllProductMaterialCollection)
            {
                if (!item.IsSelected)
                    continue;
                vm.AddProductMaterialQuantity(item.Material);
            }
        }

        void _editProductVM_ProductDeleted(Guid productID)
        {
            var vm = _allProductCollection.FirstOrDefault(p => p.ProductID == productID);
            if (vm == null)
                return;

            _allProductCollection.Remove(vm);
        }

        bool OnInwardProductINUpdated(ProductViewModel product)
        {
            List<MaterialViewModel> coll = new List<MaterialViewModel>();
            foreach (var item in product.MaterialsQuantity)
            {
                var material = _allMaterialCollection.Where(m => m.MaterialID == item.MaterialID).FirstOrDefault();
                if (material == null)
                    return false;

                if (material.Quantity < item.MaterialQuantity)
                {
                    StringBuilder strmessage = new StringBuilder();
                    strmessage.AppendLine(string.Format("The product '{0}' requires '{1}' units of material '{2}'", product.ProductName, item.MaterialQuantity, item.MaterialName));
                    strmessage.AppendLine(string.Format("The material quantity ({0}) for the material '{1}' is less than that required for manufacturing the product", material.Quantity, material.MaterialName));
                    strmessage.AppendLine();
                    strmessage.AppendLine("The product cannot be consumed for manufacturing.");
                    ShowErrorMessageBox(strmessage.ToString(),"Consume Product");
                    return false;
                }

                coll.Add(material);

            }
            bool bUpdated = _inwardProductINVM.UpdateProductProperties(product,coll);   
            if(bUpdated)
                InwardProductOUT.InwardOUTProductCollection.Add(product);
            return bUpdated;
        }

        bool OnInwardProductOUTUpdated(ProductViewModel product)
        {
            _inwardProductOUTVM.UpdateProductProperties(product);
            OutwardProduct.OutwardProductCollection.Add(product);
            return true;
        }

        bool OnOutwardProductUpdated(ProductViewModel product)
        {
            _outwardProductVM.UpdateProductProperties(product);
            ProductGrid.RaisePropertyChanged();
            return true;
        }

        void materialCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            MaterialViewModel matVM;
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    if (e.NewItems == null || e.NewItems.Count < 1)
                        return;

                    matVM = e.NewItems[0] as MaterialViewModel;
                    if (matVM == null)
                        return;

                    if (matVM.MaterialType == EnumMaterialType.Manufacturing)
                    {
                        _allMaterialCollection.Add(matVM);
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    if (e.OldItems == null || e.OldItems.Count < 1)
                        return;
                    matVM = e.OldItems[0] as MaterialViewModel;
                    if (matVM == null)
                        return;

                    if (matVM.MaterialType == EnumMaterialType.Manufacturing)
                    {
                        _allMaterialCollection.Remove(matVM);
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    break;
            }
        }
    }
}
